import * as Cesium from '@cesiumjs';

var scratchCartesian = void 0;
var scratchCartesian2 = void 0;
var scratchCarto = void 0;

var xTable2 = [];
var yTable2 = [];

// 增加自动过滤的功能，避免xTable中有相同元素
function cesiumInterpolate(d, xTable2, yTable2, yStride, result) {
  if (xTable2.length > 2) {
    for (var start = xTable2.length - 1; start > 1; start--) {
      if (xTable2[start] <= xTable2[start - 1]) {
        xTable2.splice(start, 1);
        yTable2.splice(start * 3, yStride);
      }
    }
  }

  return Cesium.HermitePolynomialApproximation.interpolateOrderZero(d, xTable2, yTable2, yStride, result);
}

function interpolate(d, xTable, yTable, yStride, result) {
  scratchCartesian = scratchCartesian || new Cesium.Cartesian3();
  scratchCarto = scratchCarto || new Cesium.Cartographic();

  d > xTable[xTable.length - 1] && (d = xTable[xTable.length - 1]);

  var n = xTable.findIndex(function(e) {
    return e >= d;
  });

  var lastIndex = n + 1 > xTable.length - 1 ? xTable.length - 1 : n + 1;
  var firstIndex = n - 2 < 0 ? 0 : n - 2;

  xTable2.length = 0;
  yTable2.length = 0;

  for (var ii = firstIndex; ii <= lastIndex; ++ii) {
    xTable2.push(xTable[ii]);
    yTable2.push(yTable[ii * 3], yTable[ii * 3 + 1], yTable[ii * 3 + 2]);
  }

  // result = Cesium.HermitePolynomialApproximation.interpolateOrderZero(d, xTable2, yTable2, yStride, result);
  result = cesiumInterpolate(d, xTable2, yTable2, yStride, result);
  return result;
}


var scratchResult = [];
var scratchXTable = [];
var scratchYTable = [];

function interpolatePositions(positions, splitNum) {
  var _Cesium$Cartesian, _result;

  var loop = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  var result = arguments[3];

  scratchCartesian = scratchCartesian || new Cesium.Cartesian3();
  scratchCartesian2 = scratchCartesian2 || new Cesium.Cartesian3();
  scratchCarto = scratchCarto || new Cesium.Cartographic();

  var l = positions.length;
  var tl = 0;
  var xTable = scratchXTable;
  var yTable = scratchYTable;
  xTable.length = 0;
  yTable.length = 0;
  var cartesian = (_Cesium$Cartesian = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian, (0,
    _toConsumableArray3.default)(positions[0]).concat([undefined, scratchCartesian]));
  xTable.push(0);
  yTable.push(cartesian.x, cartesian.y, cartesian.z);
  for (var i = 0; i < l - 1; ++i) {
    var _Cesium$Cartesian2, _Cesium$Cartesian3;

    var _cartesian = (_Cesium$Cartesian2 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian2, (0,
      _toConsumableArray3.default)(positions[i]).concat([undefined, scratchCartesian]));
    var cartesian2 = (_Cesium$Cartesian3 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian3, (0,
      _toConsumableArray3.default)(positions[i + 1]).concat([undefined, scratchCartesian2]));
    var d = Cesium.Cartesian3.distance(_cartesian, cartesian2);
    if (d > 0.000001) {
      tl += d;
      xTable.push(tl);
      yTable.push(cartesian2.x, cartesian2.y, cartesian2.z);
    }
  }

  if (loop) {
    var _Cesium$Cartesian4, _Cesium$Cartesian5;

    var first = (_Cesium$Cartesian4 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian4, (0,
      _toConsumableArray3.default)(positions[0]).concat([undefined, scratchCartesian]));
    var last = (_Cesium$Cartesian5 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian5, (0,
      _toConsumableArray3.default)(positions[positions.length - 1]).concat([undefined, scratchCartesian2]));
    var _d = Cesium.Cartesian3.distance(last, first);

    if (_d > 0.000001) {
      // 首尾位置相同，就不当作是loop了。理论上将此时应该去除一个点，然后在做下面的事情，此处直接不做了。
      tl += _d;

      xTable.unshift(-_d);
      yTable.unshift(last.x, last.y, last.z);

      xTable.push(tl);
      yTable.push(first.x, first.y, first.z);

      xTable.push(tl + xTable[2]);
      yTable.push(yTable[2 * 3 + 0], yTable[2 * 3 + 1], yTable[2 * 3 + 2]);
    }
  }

  var avl = tl / splitNum;
  var newPositions = scratchResult;
  result = result || [];
  newPositions.length = 0;
  for (var _i = 0; _i <= splitNum; ++_i) {
    var _Cesium$Cartesian6;

    var _d2 = _i * avl;
    var position = interpolate(_d2, xTable, yTable, 3); // new []
    var _cartesian2 = (_Cesium$Cartesian6 = Cesium.Cartesian3).fromElements.apply(_Cesium$Cartesian6, (0,
      _toConsumableArray3.default)(position).concat([scratchCartesian]));
    var carto = Cesium.Cartographic.fromCartesian(_cartesian2, undefined, scratchCarto);
    position.splice(0, 3, carto.longitude, carto.latitude, carto.height);
    newPositions.push(position);
  }

  (_result = result).splice.apply(_result, [0, result.length].concat(newPositions));

  return result;
}

// ds表示每一段的累计步长
function interpolatePosition(d, ds, positions, result) {
  var _Cesium$Cartesian8;

  if (positions.length < 1) {
    return undefined;
  }

  if (ds.length !== positions.length) {
    return;
    // throw new Error('length必须一致！');
  }

  var n = ds.findIndex(function(e) {
    return e >= d;
  });
  n < 0 && (n = ds.length - 1);

  var lastIndex = n + 1 > positions.length - 1 ? positions.length - 1 : n + 1;
  var firstIndex = n - 2 < 0 ? 0 : n - 2;

  xTable2.length = 0;
  yTable2.length = 0;

  for (var ii = firstIndex; ii <= lastIndex; ++ii) {
    var _Cesium$Cartesian7;

    xTable2.push(ds[ii]);

    var _cartesian3 = (_Cesium$Cartesian7 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian7, (0,
      _toConsumableArray3.default)(positions[ii]).concat([undefined, scratchCartesian]));
    yTable2.push(_cartesian3.x, _cartesian3.y, _cartesian3.z);
  }

  var interpolateCartesian = Cesium.HermitePolynomialApproximation.interpolateOrderZero(d, xTable2, yTable2, 3);
  var cartesian = (_Cesium$Cartesian8 = Cesium.Cartesian3).fromElements.apply(_Cesium$Cartesian8, (0,
    _toConsumableArray3.default)(interpolateCartesian).concat([scratchCartesian]));
  var carto = Cesium.Cartographic.fromCartesian(cartesian, undefined, scratchCarto);

  result = result || [0, 0, 0];
  result.splice(0, 3, carto.longitude, carto.latitude, carto.height);

  return result;
}

var scratchHPR = void 0;
var scrathQ1 = void 0;
var scrathQ2 = void 0;
var scrathQ3 = void 0;

function interpolateRotation(d, ds, rotations, result) {
  var _scratchHPR, _scratchHPR2;

  if (rotations.length < 1) {
    return undefined;
  }

  result = result || [0, 0, 0];

  if (ds.length !== rotations.length) {
    return;
    // throw new Error('length必须一致！');
  }

  scratchHPR = scratchHPR || new Cesium.HeadingPitchRoll();
  scrathQ1 = scrathQ1 || new Cesium.Quaternion();
  scrathQ2 = scrathQ2 || new Cesium.Quaternion();
  scrathQ3 = scrathQ3 || new Cesium.Quaternion();

  var n = ds.findIndex(function(e) {
    return e >= d;
  });
  n < 0 && (n = ds.length - 1);

  if (n === 0) {
    var _result2;

    (_result2 = result).splice.apply(_result2, [0, 3].concat((0, _toConsumableArray3.default)(rotations[0])));
    return result;
  }

  var ratio = n === 0 ? 0 : (d - ds[n - 1]) / (ds[n] - ds[n - 1]);
  ratio > 1.0 && (ratio = 1.0);

  var q1 = Cesium.Quaternion.fromHeadingPitchRoll((_scratchHPR = scratchHPR).xbsjFromArray.apply(_scratchHPR, (
    0, _toConsumableArray3.default)(rotations[n - 1])), scrathQ1);
  var q2 = Cesium.Quaternion.fromHeadingPitchRoll((_scratchHPR2 = scratchHPR).xbsjFromArray.apply(_scratchHPR2,
    (0, _toConsumableArray3.default)(rotations[n])), scrathQ2);
  var q3 = Cesium.Quaternion.fastSlerp(q1, q2, ratio, scrathQ3);

  var hpr = Cesium.HeadingPitchRoll.fromQuaternion(q3, scratchHPR);
  if (hpr) {
    result.splice(0, 3, hpr.heading, hpr.pitch, hpr.roll);
    return result;
  }

  return undefined;
}

function computDs(positions, rotations) {
  var loop = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  var resultDs = arguments[3];
  var resultPositions = arguments[4];
  var resultRotations = arguments[5];

  var l = positions.length;

  var tl = 0;
  var ds = resultDs || [];
  ds.length = 0;

  if (l <= 0) {
    return ds;
  }

  ds.push(0);
  for (var i = 0; i < l - 1; ++i) {
    var _Cesium$Cartesian9, _Cesium$Cartesian10;

    var cartesian = (_Cesium$Cartesian9 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian9, (0,
      _toConsumableArray3.default)(positions[i]).concat([undefined, scratchCartesian]));
    var cartesian2 = (_Cesium$Cartesian10 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian10, (0,
      _toConsumableArray3.default)(positions[i + 1]).concat([undefined, scratchCartesian2]));
    var d = Cesium.Cartesian3.distance(cartesian, cartesian2);
    tl += d;
    ds.push(tl);
  }

  if (loop && l > 2) {
    var _Cesium$Cartesian11, _Cesium$Cartesian12;

    resultPositions.length = 0;

    resultPositions.push.apply(resultPositions, (0, _toConsumableArray3.default)(positions));

    resultRotations.length = 0;
    resultRotations.push([0, 0, 0]);
    resultRotations.push.apply(resultRotations, (0, _toConsumableArray3.default)(rotations));
    resultRotations.push([].concat((0, _toConsumableArray3.default)(rotations[0])));
    resultRotations.push([0, 0, 0]);

    var first = (_Cesium$Cartesian11 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian11, (0,
      _toConsumableArray3.default)(positions[0]).concat([undefined, scratchCartesian]));
    var last = (_Cesium$Cartesian12 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian12, (0,
      _toConsumableArray3.default)(positions[positions.length - 1]).concat([undefined, scratchCartesian2]));
    var _d3 = Cesium.Cartesian3.distance(last, first);
    tl += _d3;

    ds.unshift(-_d3);
    resultPositions.unshift([].concat((0, _toConsumableArray3.default)(positions[positions.length - 1])));

    ds.push(tl);
    resultPositions.push([].concat((0, _toConsumableArray3.default)(positions[0])));

    ds.push(tl + ds[2]);
    resultPositions.push([].concat((0, _toConsumableArray3.default)(resultPositions[2])));
  }

  return ds;
}


export {
  interpolatePosition,
  interpolateRotation,
  computDs,
  interpolatePositions,
  interpolate
}

